using System;
using System.Text;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;

namespace My.IdlConverter.Core.Util
{
    public class ReflectHelper
    {
        public static string ResolvePathByAssembly(Assembly assembly, string relativePath)
        {
            string codebase = assembly.CodeBase;
            if (codebase.IndexOf("file:///") != -1)
                codebase = codebase.Remove(0, "file:///".Length);
            int index = codebase.LastIndexOf('/');
            string fullPath = System.IO.Path.Combine(codebase.Substring(0, index), relativePath);

            return fullPath;
        }

        public static Types.IType ConstructTypeObj(Type type)
        {
            ConstructorInfo ctor = type.GetConstructor(new Type[] { });
            Types.IType target = ctor.Invoke(null) as Types.IType;
            Debug.Assert(target != null);
            return target;
        }

        public static System.Type ClassForName(string name)
        {
            TypeQualifiedName parsedName = TypeNameParser.Parse(name);
            System.Type result = TypeFromAssembly(parsedName);
            if (result == null)
            {
                throw new TypeLoadException("Could not load type '" + parsedName + "', check that type and assembly names are correct");
            }
            return result;
        }

        public static Type TypeFromAssembly(TypeQualifiedName qname)
        {
            log4net.ILog log = log4net.LogManager.GetLogger(typeof(ReflectHelper));

            try
            {
                Type type = Type.GetType(qname.Type);

                if (type != null)
                {
                    return type;
                }

                if (qname.Assembly == null)
                {
                    log.Warn("Could not load type " + qname.Type+ ". Possible cause: no assembly name specified.");
                    return null;
                }

                Assembly assembly = Assembly.Load(qname.Assembly);

                if (assembly == null)
                {
                    log.Warn("Could not load type " + qname.Type + ". Possible cause: incorrect assembly name specified.");
                    return null;
                }

                type = assembly.GetType(qname.Type);

                if (type == null)
                {
                    log.Warn("Could not load type " + qname.Type+ ".");
                    return null;
                }

                return type;
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                {
                    log.Error("Could not load type " + qname.Type + ".", e);
                }
                return null;
            }
        }
    }
}
